package cn.hwadee.muying.commons.mail.receiver;

import cn.hwadee.muying.entity.Mail;
import cn.hwadee.muying.entity.MailMessage;
import cn.hwadee.muying.entity.SyncTime;
import cn.hwadee.muying.enums.MailSetting;
import com.sun.mail.util.MailConnectException;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import javax.mail.*;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @描述: 通用邮件接收器
 * @作者: Jing
 * @日期: 2018/1/26
 */
public abstract class AbstractReceiver {

    protected static String TIME_OUT = "300000";  //超时重试5min
    protected static String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
    protected static String TARGET_ADDRESS = "@marketplace.amazon.com";  //目标邮箱地址
    protected Mail mail;
    private int tryCount=3;//邮箱连接超时次数
    private Logger log = Logger.getLogger(AbstractReceiver.class);

    public AbstractReceiver(Mail _mail){
        this.mail = _mail;
        MailSetting.setMailSetting(mail);
    }

    public abstract List<MailMessage> fetch(SyncTime syncTime) throws Exception;

    public void parseContent(String s,MailMessage mailMessage) throws Exception{
        List<String> contents = new ArrayList<>();
        String url = "";
        String splitLine = "------------- End message -------------";
        String urlMark = "To mark this message as no response needed, click here:";
        String begin="------------- Begin message ------------";
        String end="- Amazon Marketplace";//此邮件是回复邮件，包含上几次交互的邮件信息，到- Amazon Marketplace为止
        boolean lineUp = true;
        String[] lines = s.split("\n");
        for(String line:lines){
            if(StringUtils.isNotEmpty(line.trim())){
                if(line.contains(begin)){//跳过------------- Begin message ------------
                    continue;
                }
                if(lineUp){
                    if(line.contains(splitLine)||line.contains(end)){
                        lineUp = false;
                        continue;
                    }else {
                        contents.add(line);
                    }
                }else {
                    if(line.contains(urlMark)){
                        url = line.substring(urlMark.length());
                        break;
                    }
                }
            }
        }
        mailMessage.setMsg(StringUtils.join(contents.toArray(),"\n"));
        mailMessage.setNoReplyUrl(url);
    }

    public void getMailTextContent(Part part, StringBuffer content) throws Exception {
        boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
            if (part.isMimeType("text/*") && !isContainTextAttach) {
                content.append(part.getContent().toString());
            } else if (part.isMimeType("message/rfc822")) {
                getMailTextContent((Part)part.getContent(),content);
            } else if (part.isMimeType("multipart/*")) {
                Multipart multipart = (Multipart) part.getContent();
                int partCount = multipart.getCount();
                for (int i = 0; i < partCount; i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    getMailTextContent(bodyPart,content);
                }
            }
    }

    public void initProperties(Properties props) throws Exception{
        MailSetting mailSetting=mail.getRecMailSetting();
        try{
        log.info(mail.getEmail()+"当前邮箱设置为:"+mailSetting);
        log.info(mail.getEmail()+"协议是:"+mailSetting.getProtocol()+"属性对象:"+props);
            props.setProperty("mail.store.protocol", mailSetting.getProtocol());
        }catch (Exception e){
                if(null==props){
                    log.info("空指针就是你了props:"+props);
                }
                log.info("空指针属性: props: "+props+" mailSetting:"+ mailSetting);
                log.error("空指针异常:",e);
        }


        //使用pop3协议
        if(mailSetting.getProtocol().equals("pop3")){
            props.setProperty("mail.pop3.port", mailSetting.getPort());
            props.setProperty("mail.pop3.timeout", TIME_OUT);
            if(mailSetting.isSSL()){
                //使用SSL协议
                Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
                props.setProperty("mail.pop3.ssl.enable", "true");
                props.setProperty("mail.pop3.socketFactory.port",mail.getRecMailSetting().getPort());
            }
        }else{//使用imap协议
            props.setProperty("mail.imap.port",mailSetting.getPort());
            props.setProperty("mail.imap.timeout", TIME_OUT);
            props.setProperty("mail.imap.partialfetch", "false");
            if(mailSetting.isSSL()){
                Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);
                props.setProperty("mail.imap.socketFactory.port",mailSetting.getPort());
                props.setProperty("mail.imap.socketFactory.fallback", "false");
            }
        }

    }


    /**
     * 尝试连接邮箱服务器
     * @param store
     * @param mail
     */
    public boolean tryConnect(Store store, Mail mail){
        for(int i=0;i<tryCount;i++){
            try {
                String host=mail.getRecMailSetting().getHost();
                String port=mail.getRecMailSetting().getPort();
                String mailAddr=mail.getEmail();
                String authCode=mail.getAuthCode();
                log.info(mail.getEmail()+"正在验证连接服务器:"+" host:"+host+"   auth:"+authCode+"  port:"+port);
                store.connect(host,mailAddr,authCode);
                log.info(mail.getEmail()+"连接服务器:"+" host:"+host+"   auth:"+authCode+"  port:"+port+" 成功!");
                return true;
            } catch (MessagingException e) {
                if(e instanceof MailConnectException){
                    try {
                        log.error(mail.getEmail()+"网络连接失败，开始休眠，休眠五分钟",e);
                        Thread.sleep(300000);
                    } catch (InterruptedException e1) {
                        log.error("线程睡眠错误",e1);
                        e1.printStackTrace();
                    }
                }else {
                    log.error(mail.getEmail()+"接收邮件失败!",e);
                }
                e.printStackTrace();
            }
        }
       return false;
    }

}
